home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 2000 #1 / Amiga Plus CD - 2000 - No. 1.iso / Tools / Dev / Meshwriter / geo.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-12-03  |  12.2 KB  |  377 lines

  1. /*
  2. **      $VER: geo.c 1.00 (27.03.1999)
  3. **
  4. **      Creation date : 19.02.1999
  5. **
  6. **      Description       :
  7. **         Standart saver module for meshwriter.library.
  8. **         Saves the mesh as Videoscape file.
  9. **
  10. **
  11. **      Written by Stephan Bielmann
  12. **
  13. */
  14.  
  15. /*************************** Includes *******************************/
  16.  
  17. /*
  18. ** Ansi C includes
  19. */
  20. #include <math.h>
  21.  
  22. /*
  23. ** Amiga includes
  24. */
  25. #include <dos/dos.h>
  26. #include <dos/stdio.h>
  27.  
  28. #include <clib/dos_protos.h>
  29. #include <clib/alib_stdio_protos.h>
  30.  
  31. /*
  32. ** Project includes
  33. */
  34. #include "meshwriter_private.h"
  35. #include "utilities.h"
  36.  
  37. /**************************** Defines *******************************/
  38.  
  39. /*
  40. ** Number of elements in the buffers
  41. */
  42. #define Ci_MAXVERINPOLY 200    // maximum vertices in a polygon
  43. #define Ci_BUFFERV      100    // vector buffer
  44.  
  45. /*********************** Type definitions ***************************/
  46.  
  47. /*
  48. ** This struct is created just for storing Videoscape default
  49. ** color palette table.
  50. */
  51. typedef struct {
  52.         UBYTE  red, green, blue;
  53. } GEOColor;
  54.  
  55. /*
  56. ** Vector structure for the binary format
  57. */
  58. typedef struct {
  59.     FLOAT x,y,z;
  60. } GEOVector;
  61.  
  62. typedef struct {
  63.     UBYTE name[4];
  64.     UWORD nvertices;
  65. } GEOHead;
  66.  
  67. /*************************** Variables ******************************/
  68.  
  69. /*
  70. ** Videoscape equivalent rgb colors.
  71. */
  72. static const GEOColor colorTbl[] = {
  73. {  0,  0,  0},{  0,  0,178},{  0,178,  0},{  0,178,178},{178,  0,  0},{255,127,255},
  74. {204,153,102},{127,127,127},{  0,  0,  0},{102,102,255},{102,255,102},{  0,255,100},
  75. {255,102,102},{255,204,255},{255,255,  0},{255,255,255}
  76. };
  77.  
  78. /********************** Private functions ***************************/
  79.  
  80. /********************************************************************\
  81. *                                                                    *
  82. * Name         : magnitude                                           *
  83. *                                                                    *
  84. * Description  : Calculates the magnitude of a color vector.         *
  85. *                                                                    *
  86. * Arguments    : x,y,z : Color vector.                               *
  87. *                                                                    *
  88. * Return Value : Vector its magnitude.                               *
  89. *                                                                    *
  90. * Comment      :                                                     *
  91. *                                                                    *
  92. \********************************************************************/
  93. static ULONG magnitude(LONG x, LONG y, LONG z)
  94. {
  95.     return(sqrt(x*x + y*y + z*z));
  96. }
  97.  
  98. /********************************************************************\
  99. *                                                                    *
  100. * Name         : index2Color                                         *
  101. *                                                                    *
  102. * Description  : Converts a GEO color index into a RGB color.        *
  103. *                                                                    *
  104. * Arguments    : index : The color index.                            *
  105. *                                                                    *
  106. * Return Value : Vector its magnitude.                               *
  107. *                                                                    *
  108. * Comment      :                                                     *
  109. *                                                                    *
  110. \********************************************************************/
  111. static GEOColor index2Color(ULONG index)
  112. {
  113.     static GEOColor col;
  114.     
  115.     /*
  116.     ** Check range
  117.     */
  118.     if (index >= 0 && index < sizeof(colorTbl)/sizeof(GEOColor)) {
  119.         /*
  120.         ** return table entry
  121.         */
  122.         col.red = colorTbl[index].red;
  123.         col.green= colorTbl[index].green;
  124.         col.blue= colorTbl[index].blue;
  125.  
  126.         return (col);
  127.     }
  128.  
  129.     /*
  130.     ** Out-of-range color is white, like undefined.
  131.     */
  132.     col.red = 255;
  133.     col.green= 255;
  134.     col.blue= 255;
  135.                 
  136.     return (col);
  137. }
  138.  
  139. /********************************************************************\
  140. *                                                                    *
  141. * Name         : color2GEO                                           *
  142. *                                                                    *
  143. * Description  : Matches the nearest color available in the GEO      *
  144. *                color palette.                                      *
  145. *                                                                    *
  146. * Arguments    : red,green,blue : Color values.                      *
  147. *                                                                    *
  148. * Return Value : GEO color index.                                    *
  149. *                                                                    *
  150. * Comment      :                                                     *
  151. *                                                                    *
  152. \********************************************************************/
  153. static ULONG color2GEO (UBYTE red, UBYTE green, UBYTE blue)
  154. {
  155.     ULONG        i;
  156.     ULONG        index = 1;
  157.     GEOColor    current;
  158.     LONG        best;
  159.     LONG        difference;
  160.   
  161.     current = index2Color(index);
  162.     best =  magnitude(current.red-red,current.green-green,current.blue-blue);
  163.  
  164.     for (i = 0; i < sizeof(colorTbl)/sizeof(GEOColor); i++) {
  165.         current = index2Color(i);
  166.         difference = magnitude(current.red-red,current.green-green,current.blue-blue);
  167.         if (difference < best) {
  168.             best = difference;
  169.             index = i;
  170.         }
  171.     }
  172.  
  173.     return (index);
  174. }
  175.  
  176. /********************** Public functions ****************************/
  177.  
  178. /********************************************************************\
  179. *                                                                    *
  180. * Name         : write3GEOA                                          *
  181. *                                                                    *
  182. * Description  : Writes a standart Videoscape ASCII file.            *
  183. *                                                                    *
  184. * Arguments    : geofile IN  : An already opened file stream.        *
  185. *                mesh    IN  : Pointer to the mesh.                  *
  186. *                                                                    *
  187. * Return Value : RCNOERROR                                           *
  188. *                RCWRITEDATA                                         *
  189. *                RCVERTEXINPOLYGONOVERFLOW                           *
  190. *                                                                    *
  191. * Comment      : #Vertices per polygon limited to 100 by myself !    *
  192. *                                                                    *
  193. \********************************************************************/
  194. ULONG write3GEOA(BPTR geofile, TOCLMesh *mesh) {
  195.     UBYTE                         buffer[500];
  196.     ULONG                        pbuffer[Ci_MAXVERINPOLY];    // Ci_MAXVERINPOLY * sizeof(ULONG)    polygon vertex buffer
  197.     TOCLVertexNode                *ver=NULL;
  198.     TOCLPolygonNode             *pln=NULL;
  199.     TOCLPolygonsVerticesNode    *plv=NULL;
  200.     LONG                        polybufstate;
  201.  
  202. /* As the binary is limmited with words for the vertex counts I suppose the ASCII too */
  203.  
  204.     /*
  205.     ** Write the header and the number of vertices
  206.     */
  207.     if (FPrintf(geofile,"3DG1\n%ld\n",mesh->vertices.numberOfVertices)==ENDSTREAMCH) return(RCWRITEDATA);
  208.  
  209.     /*
  210.     ** Write the vertices
  211.     */              
  212.     if(mesh->vertices.firstNode!=NULL) {
  213.         ver=mesh->vertices.firstNode;
  214.         do {
  215.             TOCLVertex v=ver->vertex;
  216.             sprintf(buffer,"%g %g %g\n",v.x,v.z,v.y);
  217.             if(FPuts(geofile,buffer)!=DOSFALSE) return(RCWRITEDATA);
  218.             ver=ver->next;
  219.         } while(ver!=NULL);
  220.     }
  221.  
  222.     /*
  223.     ** Write the polygons
  224.     */
  225.       if(mesh->polygons.firstNode!=NULL) {             
  226.             pln=mesh->polygons.firstNode;
  227.         do {                
  228.             if(pln->firstNode!=NULL) {  
  229.                 TOCLColor col=pln->materialNode->diffuseColor;
  230.  
  231.                 plv=pln->firstNode;
  232.                 if (FPrintf(geofile,"%ld ",pln->numberOfVertices)==ENDSTREAMCH) return(RCWRITEDATA);
  233.  
  234.                 // initialize the buffer state
  235.                 polybufstate=Ci_MAXVERINPOLY-1;
  236.  
  237.                 // transform from counterclockwise to clockwise
  238.                 do {
  239.                     pbuffer[polybufstate--]=plv->vertexNode->index-1;
  240.  
  241.                     // check if there are to much vertices in this polygon
  242.                     if (polybufstate<0) {
  243.                         return(RCVERTEXINPOLYGONOVERFLOW);
  244.                     }
  245.  
  246.                     plv=plv->next;
  247.                 } while(plv!=NULL);
  248.  
  249.                 // write the indexes
  250.                 while(++polybufstate<Ci_MAXVERINPOLY) {
  251.                     if (FPrintf(geofile,"%ld ",pbuffer[polybufstate])==ENDSTREAMCH) return(RCWRITEDATA);
  252.                 }
  253.  
  254.                 // write the material index
  255.                 if (FPrintf(geofile,"%ld\n",color2GEO(col.r,col.g,col.b))==ENDSTREAMCH) return(RCWRITEDATA);
  256.             }
  257.             pln=pln->next;
  258.         } while(pln!=NULL);    
  259.     }
  260.  
  261.     return(RCNOERROR);
  262. }
  263.  
  264. /********************************************************************\
  265. *                                                                    *
  266. * Name         : write3GEOB                                          *
  267. *                                                                    *
  268. * Description  : Writes a standart Videoscape binary file.           *
  269. *                                                                    *
  270. * Arguments    : geofile IN  : An already opened file stream.        *
  271. *                mesh    IN  : Pointer to the mesh.                  *
  272. *                                                                    *
  273. * Return Value : RCNOERROR                                           *
  274. *                RCWRITEDATA                                         *
  275. *                RCVERTEXINPOLYGONOVERFLOW                           *
  276. *                                                                    *
  277. * Comment      : #Vertices per polygon limited to 100 by myself !    *
  278. *                                                                    *
  279. \********************************************************************/
  280. ULONG write3GEOB(BPTR geofile, TOCLMesh *mesh) {
  281.     UWORD                        pbuffer[Ci_MAXVERINPOLY];    // Ci_MAXVERINPOLY * sizeof(UWORD)    polygon vertex buffer
  282.     GEOVector                    vbuffer[Ci_BUFFERV];        // Ci_BUFFERV * sizeof(GeoVector)    vector buffer
  283.     TOCLVertexNode                *ver=NULL;
  284.     TOCLPolygonNode             *pln=NULL;
  285.     TOCLPolygonsVerticesNode    *plv=NULL;
  286.     GEOHead                    gh;
  287.     LONG                        polybufstate;
  288.     ULONG                        bufferstate;
  289.     UWORD                         w;
  290.  
  291. /* As the binary is limmited with words for the vertex counts I suppose the ASCII too */
  292.  
  293.     /*
  294.     ** Write the header and the number of vertices
  295.     */
  296.     setUBYTEArray(gh.name,"3DB1",4);
  297.     gh.nvertices=mesh->vertices.numberOfVertices;
  298.     if(FWrite(geofile,&gh,sizeof(gh),1)!=1) return(RCWRITEDATA);    
  299.  
  300.     /*
  301.     ** Write the vertices
  302.     */              
  303.     if(mesh->vertices.firstNode!=NULL) {
  304.         ver=mesh->vertices.firstNode;
  305.  
  306.         // initialize the buffer state
  307.         bufferstate=0;
  308.  
  309.         do {
  310.             TOCLVertex v=ver->vertex;
  311.  
  312.             vbuffer[bufferstate].x=v.x;
  313.             vbuffer[bufferstate].y=v.y;
  314.             vbuffer[bufferstate].z=v.z;
  315.  
  316.             // increment the bufferstate and 
  317.             // check if the buffer is full and write and initialize it
  318.             if (++bufferstate==Ci_BUFFERV) {
  319.                 if(FWrite(geofile,&vbuffer,Ci_BUFFERV*sizeof(GEOVector),1)!=1) return(RCWRITEDATA);
  320.                 bufferstate=0;
  321.             }
  322.  
  323.             ver=ver->next;
  324.         } while(ver!=NULL);
  325.  
  326.             // write the rest of the buffer if there is any
  327.             if (bufferstate!=0) {
  328.                 if(FWrite(geofile,&vbuffer,bufferstate*sizeof(GEOVector),1)!=1) return(RCWRITEDATA);
  329.             }            
  330.     }
  331.  
  332.     /*
  333.     ** Write the polygons
  334.     */
  335.       if(mesh->polygons.firstNode!=NULL) {             
  336.             pln=mesh->polygons.firstNode;
  337.         do {                
  338.             if(pln->firstNode!=NULL) {  
  339.                 TOCLColor col=pln->materialNode->diffuseColor;
  340.  
  341.                 plv=pln->firstNode;
  342.  
  343.                 // initialize the buffer state
  344.                 polybufstate=Ci_MAXVERINPOLY-1;
  345.  
  346.                 // transform from counterclockwise to clockwise
  347.                 do {
  348.                     pbuffer[polybufstate--]=plv->vertexNode->index-1;
  349.  
  350.                     // check if there are to much vertices in this polygon
  351.                     if (polybufstate<0) {
  352.                         return(RCVERTEXINPOLYGONOVERFLOW);
  353.                     }
  354.  
  355.                     plv=plv->next;
  356.                 } while(plv!=NULL);
  357.  
  358.                 // write the number of vertices in this polygon
  359.                 w=pln->numberOfVertices;
  360.                 if(FWrite(geofile,&w,sizeof(UWORD),1)!=1) return(RCWRITEDATA);                      
  361.  
  362.                 // write down the buffer
  363.                 if(FWrite(geofile,&pbuffer[polybufstate+1],w*sizeof(UWORD),1)!=1) return(RCWRITEDATA);                      
  364.  
  365.                 // write the material index
  366.                 w=color2GEO(col.r,col.g,col.b);
  367.                 if(FWrite(geofile,&w,sizeof(UWORD),1)!=1) return(RCWRITEDATA);                      
  368.             }
  369.             pln=pln->next;
  370.         } while(pln!=NULL);    
  371.     }
  372.  
  373.     return(RCNOERROR);
  374. }
  375.  
  376. /************************* End of file ******************************/
  377.